#include "..\os\kernel.h"
#include "..\common\led.h"
#include "..\common\util.h"
#include "testTasks.h"
#include <avr/eeprom.h>

/*!
 @brief Ping task
 */
void Ping1()
{
	for(;;){
		//void Ping1()
		enable_led(LED_D5_GREEN);
		Task_Next();
	}
}

/*!
 @brief Ping task
 */
void Ping2()
{
	for(;;){
		//void Ping2()
		enable_led(LED_D5_GREEN);
		Task_Next();
	}
}

/*!
 @brief Ping task
 */
void Ping3()
{
	for(;;){
		//void Ping3()
		enable_led(LED_D5_GREEN);
		Task_Next();
	}
}

/*!
 @brief Ping task
 */
void Ping4()
{
	for(;;){
		//void Ping4()
		enable_led(LED_D5_GREEN);
		Task_Next();
	}
}

/*!
 @brief Ping task
 */
void Ping5()
{
	for(;;){
		//void Ping5()
		enable_led(LED_D5_GREEN);
		Task_Next();
	}
}

uint16_t return_time, next_time;
uint16_t *addr = 0;

/*!
 @brief Ping task with EEPROM log code
 */
void PingE()
{
	for(;;){
		return_time = TCNT1;
		eeprom_write_word(addr++, return_time - next_time);
		next_time = TCNT1;

		enable_led(LED_D5_GREEN);
		Task_Next();
	}
}


/*!
 @brief Pong task
 */
void Pong1() 
{
	for(;;) {
		//void Pong1() 
		disable_led(LED_D5_GREEN);
		Task_Next();

	}
}

/*!
 @brief Pong task
 */
void Pong2() 
{
	for(;;) {
		//void Pong2() 
		disable_led(LED_D5_GREEN);
		Task_Next();

	}
}

/*!
 @brief Pong task
 */
void Pong3() 
{
	for(;;) {
		//void Pong3() 
		disable_led(LED_D5_GREEN);
		Task_Next();

	}
}

/*!
 @brief Pong task
 */
void Pong4() 
{
	for(;;) {
		//void Pong4() 
		disable_led(LED_D5_GREEN);
		Task_Next();

	}
}


volatile EVENT *fullBuffer; //!< Event used to coordinate the Consumer and Producer tasks
volatile unsigned int Ptop=10;
volatile unsigned int Ctop=15;

/*!
 @brief Consumer Task
 */
void Consumer(){
	unsigned int arg=0;
	arg=Task_GetArg();
	
	while(1){
		// void Consumer()
		enable_led(LED_D2_GREEN);
		Event_Wait((EVENT*)fullBuffer);	// change the State to WAITING	
		Task_Next();		
	}
}

/*!
 @brief Producer Task
 */
void Producer(){
	unsigned int buffer=0;
	unsigned int arg=0;
	arg=Task_GetArg();
	
	while (1){
		// void Producer()
		buffer++;
		if (buffer<Ptop){
			enable_led(LED_D2_RED);
		} else if (buffer==Ptop){
			disable_led(LED_D2_RED);
			buffer=0;
			Event_Signal((EVENT*)fullBuffer);			
		}
		Task_Next();
	}
}

/*!
 @brief Loop Task

 Executes an infinite loop
 */
void Loop1(){
	unsigned int counter=0;
	for(;;)counter++;
}

/*!
 @brief Loop Task

 Executes an infinite loop
 */
void Loop2(){
	unsigned int counter=0;
	for(;;)counter++;
}

/*!
 @brief Loop Task

 Executes an infinite loop
 */
void Loop(){
	for(;;);
}

/*!
 @brief Counter Task

 This function use the task argument to run.
 - If the argument is equal to zero:  the internal loop is executed once and terminates the task
 - If the argument is greater than zero: The internal loop is executed for the number of times determined by the argument, reset the counter, and then call Task_Next()
 - If the argument is less than zero, the internal loop is executed for the number of times determined by the argument, resets the counter, and terminates the task
 */
void Counter1(){
	unsigned int counter=0;
	int arg=0;
	int s=1;
	arg=Task_GetArg();

	if (arg<0){
		s=-1;
		arg=arg*s;
	}	
	while(1){
		// void Counter1()
		counter++;
		if (arg == 0){
			break;
		}else if (arg == counter){
			if (s==1){
				counter=0;
				Task_Next();				
			} else {
				counter=0;
				break;
			}
		}
	}
}

/*!
 @brief Counter Task

 This function use the task argument to run.
 - If the argument is equal to zero:  the internal loop is executed once and terminates the task
 - If the argument is greater than zero: The internal loop is executed for the number of times determined by the argument, reset the counter, and then call Task_Next()
 - If the argument is less than zero, the internal loop is executed for the number of times determined by the argument, resets the counter, and terminates the task
 */
void Counter2(){
	unsigned int counter=0;
	int arg=0;
	int s=1;
	arg=Task_GetArg();

	if (arg<0){
		s=-1;
		arg=arg*s;
	}	
	while(1){
		// void Counter2()
		counter++;
		if (arg == 0){
			break;
		}else if (arg == counter){
			if (s==1){
				counter=0;
				Task_Next();				
			} else {
				break;
			}
		}
	}
}

/*!
 @brief Call the function to construct the test case scenarion
 */
void initTaskCase(int c){
	switch(c){
		case 1:
			testCase01();
			break;
		case 2:
			testCase02();
			break;
		case 3:
			testCase03();
			break;
		case 4:
			testCase04();
			break;
		case 5:
			testCase05();
			break;
		case 6:
			testCase06();
			break;
		case 7:
			testCase07();
			break;
		case 8:
			testCase08();
			break;
		case 9:
			testCase09();
			break;
		case 10:
			testCase10();
			break;
		case 11:
			testCase11();
			break;
		case 12:
			testCase12();
			break;
		case 13:
			testCase13();
			break;
		case 14:
			testCase14();
			break;
		case 15:
			testCase15();
			break;
		case 16:
			testCase16();
			break;
		case 17:
			testCase17();
			break;
		case 18:
			testCase18();
			break;
		case 19:
			testCase19();
			break;
		case 20:
			testCase20();
			break;
		case 21:
			testCase21();
			break;
		case 22:
			testCase22();
			break;
		case 23:
			testCase23();
			break;			
	}
}
